package com.cb.web.wasf.sample.web;

import com.cb.web.wasf.Message.FreeMessage;
import com.cb.web.wasf.Request;
import com.cb.web.wasf.State;
import com.cb.web.wasf.View;
import com.cb.web.wasf.View.JspView;
import com.cb.web.wasf.sample.model.BONotFoundException;
import com.cb.web.wasf.sample.model.UniqueConstraintBOException;
import com.cb.web.wasf.sample.model.ProfilBO;
import com.cb.web.wasf.sample.model.UserBO;
import com.cb.web.wasf.sample.web.ConfirmDialogState.ConfirmDialogStateHandler;
import static com.cb.web.wasf.sample.web.validation.Check.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author CBO
 */
public class UserEditState extends AbstractMenuSupportState {

    private UserListState userListState;
    private Long id;
    private String login;
    private String firstName;
    private String lastName;
    private String mail;
    private boolean enable;
    private List<ProfilBO> allProfils;
    private Set<ProfilBO> selectedProfils;
    private String password;
    private String passwordConfirmation;

    public static UserEditState creation(UserListState userListState) {
        return new UserEditState(userListState);
    }

    public static UserEditState modification(UserListState userListState, long userId) throws BONotFoundException {
        return new UserEditState(userListState, userId);
    }

    private UserEditState(UserListState userListState) {
        this.userListState = userListState;
        initForCreation();
    }

    private UserEditState(UserListState userListState, Long userId) throws BONotFoundException {
        this.userListState = userListState;
        UserBO user = ManagerLocator.getUserManager().getById(userId);
        if (user == null) {
            throw new BONotFoundException();
        } else {
            initForModification(user);
        }
    }

    public boolean isCreation() {
        return id == null;
    }

    public String getTitle() {
        return isCreation() ? "Création d'un utilisateur" : "Modification d'un utilisateur";
    }

    public boolean isEnable() {
        return enable;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    public String getPasswordConfirmation() {
        return passwordConfirmation;
    }

    public String getMail() {
        return mail;
    }

    public List<ProfilBO> getAllProfils() {
        return allProfils;
    }

    public Set<ProfilBO> getSelectedProfils() {
        return selectedProfils;
    }

    @Override
    public View getView() {
        return new JspView(this, "/WEB-INF/jsp/userEdit.jsp");
    }

    public State cancel(Request request) {
        userListState.addMessage(new FreeMessage("Opération annulée"));
        return userListState;
    }

    public State save(Request request) {
        clearMessages();
        bind(request);
        if (check(this,
                notEmpty(login, "Identifiant"),
                notEmpty(firstName, "Prénom"),
                notEmpty(lastName, "Nom"),
                notEmpty(mail, "Mail"),
                conditional(minLength(password, 8, "Mot de passe"), isCreation()),
                conditional(sameValue(password, passwordConfirmation, "Mot de passe", "Confirmation mot de passe"), isCreation()),
                mail(mail, "Mail"))) {
            if (isCreation()) {
                return processCreation();
            } else {
                return processModification();
            }
        } else {
            return this;
        }
    }

    @Override
    public State menuClick(Request request) {
        //bind(request); @TODO : Le formulaire étant différent tout est perdu si on bind...
        final State wantedState = super.menuClick(request);
        ConfirmDialogState confirmDialogState = new ConfirmDialogState(
                new ConfirmDialogStateHandler() {

                    @Override
                    public State confirm() {
                        return wantedState;
                    }

                    @Override
                    public State cancel() {
                        return UserEditState.this;
                    }
                },
                "Etes vous sûr de vouloir quitter cet écran : les modifications en cours seront perdues");
        return confirmDialogState;
    }

    private State processCreation() {
        try {
            ManagerLocator.getUserManager().create(login, password, firstName, lastName, mail, enable, allProfils);
            userListState.addMessage(new FreeMessage("Utilisateur créé"));
            userListState.loadUserListFromDatabase();
            return userListState;
        } catch (UniqueConstraintBOException eboe) {
            addMessage(new FreeMessage("Création impossible : le login indiqué est déja utilisé."));
            return this;
        }
    }

    private State processModification() {
        try {
            ManagerLocator.getUserManager().update(id, login, firstName, lastName, mail, enable, selectedProfils);
            userListState.addMessage(new FreeMessage("Utilisateur modifié"));
            userListState.loadUserListFromDatabase();
            return userListState;
        } catch (BONotFoundException ex) {
            addMessage(new FreeMessage("Modification annulée, l'utilisateur a été supprimé."));
            return userListState;
        } catch (UniqueConstraintBOException eboe) {
            addMessage(new FreeMessage("Le login indiqué est déja utilisé."));
            return this;
        }
    }

    private void initCommon() {
        allProfils = ManagerLocator.getProfilManager().getAll();
    }

    private void initForCreation() {
        initCommon();
        selectedProfils = new HashSet<ProfilBO>();
    }

    private void initForModification(UserBO user) {
        initCommon();
        id = user.getId();
        login = user.getLogin();
        firstName = user.getFirstName();
        lastName = user.getLastName();
        mail = user.getMail();
        enable = user.isEnable();
        selectedProfils = new HashSet<ProfilBO>();
        for (ProfilBO profil : allProfils) {
            if (user.getProfils().contains(profil)) {
                selectedProfils.add(profil);
            }
        }
    }

    private void bind(Request request) {
        this.login = request.getTrimmedParameter("login");
        this.firstName = request.getTrimmedParameter("firstName");
        this.lastName = request.getTrimmedParameter("lastName");
        this.mail = request.getTrimmedParameter("mail");
        this.enable = "true".equals(request.getTrimmedParameter("enable"));
        Set<String> selectProfilNames = request.getEmptyToNullParameterSet("selectedProfils");
        selectedProfils.clear();
        for (ProfilBO profil : allProfils) {
            if (selectProfilNames.contains(profil.getName())) {
                selectedProfils.add(profil);
            }
        }
        if (isCreation()) {
            this.password = request.getTrimmedParameter("password");
            this.passwordConfirmation = request.getTrimmedParameter("passwordConfirmation");
        }
    }
}
